#!/usr/bin/env bash

# __rvm_detect_system() does not support AIX
sys=$( command uname -s )
if [[ "${sys}" == AIX ]] ; then
    name_opt=-name
else
    name_opt=-iname
fi

unset GREP_COLOR
unset GREP_OPTIONS

source "$rvm_scripts_path/base"

__error_on_result()
{
  if [[ "$1" -gt 0 ]]; then
    rvm_error "$2 - Aborting now."
    return 0
  else
    return 1
  fi
}

snapshot_save()
{
  \typeset snapshot_temp_path snapshot_ruby_name_file \
    snapshot_alias_name_file snapshot_installable_file \
    snapshot_primary_ruby snapshot_ruby_order destination_path

  if [[ -z "$1" ]]
  then
    printf "%b" "

    Usage:

      rvm snapshot save name

    Description:

    Saves a snapshot describing the rvm installation
    to <name>.tar.gz in the current working directory.\

    " >&2
    return 1
  fi

  # Create the temporary directory.
  snapshot_temp_path="${rvm_tmp_path}/$$-snapshot"

  __rvm_rm_rf "$snapshot_temp_path"

  mkdir -p "$snapshot_temp_path"

  rvm_log "Backing up a list of aliases"
  __rvm_cp "$rvm_path/config/alias" "$snapshot_temp_path/"

  rvm_log "Backing up your user preferences"
  __rvm_cp "$rvm_user_path/db" "$snapshot_temp_path/"

  rvm_log "Backing up your installed packages"
  __rvm_sed -e 's/-//' -e 's/^lib//' < "$rvm_path/config/pkg" | __rvm_awk -F= '{print $1}' | sort | uniq > "$snapshot_temp_path/pkg"

  rvm_log "Backing up all of your gemsets"
  mkdir -p "$snapshot_temp_path/gems"

  (
    __rvm_cd "$snapshot_temp_path/gems"

    for snapshot_gemset in $(__rvm_list_gemset_strings)
    do

      __rvm_become "$snapshot_gemset" ; result="$?"

      __error_on_result "$result" "Error becoming ruby $snapshot_gemset" && return "$result"

      "$rvm_scripts_path/gemsets" export "${snapshot_gemset}.gems" >/dev/null ; result="$?"

      __error_on_result "$result" "Error exporting gemset contents for $snapshot_gemset" && return "$result"

      mkdir -p "./$snapshot_gemset/"

      [[ -d "$GEM_HOME/cache/" ]] && __rvm_cp -R "$GEM_HOME/cache/" "./$snapshot_gemset/"

    done
  )

  rvm_log "Backing up all of your installed rubies"

  printf "%b" "#!/usr/bin/env bash\n\nset -e\n\n" > "$snapshot_temp_path/install-rubies.sh"

  echo "source \"\$rvm_scripts_path/rvm\" || true" >> "$snapshot_temp_path/install-rubies.sh"

  snapshot_ruby_name_file="${rvm_tmp_path}/$$-rubies"
  snapshot_alias_name_file="${rvm_tmp_path}/$$-aliases"
  snapshot_installable_file="${rvm_tmp_path}/$$-installable"

  "$rvm_scripts_path/alias" list | __rvm_awk -F ' => ' '{print $1}' | sort | uniq 2>/dev/null > "$snapshot_alias_name_file"

  __rvm_list_strings | \command \tr ' ' '\n' | sort | uniq > "$snapshot_ruby_name_file"

  comm -2 -3 "$snapshot_ruby_name_file" "$snapshot_alias_name_file" > "$snapshot_installable_file"

  __rvm_rm_rf "$snapshot_ruby_name_file"
  __rvm_rm_rf "$snapshot_alias_name_file"

  snapshot_primary_ruby="$(__rvm_grep '^\(ree\|ruby-1.8.7\)' < "$snapshot_installable_file" | __rvm_grep -v '-head$' | \command \sort -r | \command \head -n1)"
  snapshot_ruby_order="$snapshot_primary_ruby $(__rvm_grep -v "$snapshot_primary_ruby" < "$snapshot_installable_file")"

  for snapshot_ruby_name in $snapshot_ruby_order
  do
    snapshot_install_command="$(__rvm_recorded_install_command "$snapshot_ruby_name")"
    if [[ -n "$snapshot_install_command" ]]
    then
      echo "rvm install $snapshot_install_command" | __rvm_sed "s#$rvm_path#'\\\"\$rvm_path\\\"'#" >> "$snapshot_temp_path/install-rubies.sh"
    else
      __rvm_become "$snapshot_ruby_name"
      ruby "$rvm_path/lib/rvm/install_command_dumper.rb" >> "$snapshot_temp_path/install-rubies.sh"
    fi
    unset snapshot_install_command
  done

  unset snapshot_ruby_name snapshot_primary_ruby

  __rvm_rm_rf "$snapshot_installable_file"

  rvm_log "Compressing snapshotting"
  destination_path="$PWD"
  (
    __rvm_cd "$snapshot_temp_path"
    __rvm_rm_rf "$destination_path/$1.tar.gz"
    __rvm_tar czf "$destination_path/$1.tar.gz" .
    result="$?"
    __error_on_result "$result" "Error creating archive $destination_path/$1.tar.gz" && return "$result"
  )

  rvm_log "Cleaning up"
  __rvm_rm_rf "$snapshot_temp_path"

  rvm_log "Snapshot complete"
}

snapshot_load()
{
  \typeset package_info snapshot_archive snapshot_temp_path \
    alias_name alias_ruby
  export rvm_create_flag

  if [[ -z "$1" ]]
  then
    echo "Usage: rvm snapshot load name" >&2
    echo "Loads a snapshot from <name>.tar.gz in the current directory." >&2
    return 1
  fi

  snapshot_archive="$PWD/$(echo "$1" | __rvm_sed 's/.tar.gz$//').tar.gz"

  if ! [[ -s "$snapshot_archive" ]]
  then
    echo "The provides snapshot '$(basename "$snapshot_archive")' doesn't exist." >&2
    return 1
  fi

  snapshot_temp_path="${rvm_tmp_path}/$$-snapshot"

  __rvm_rm_rf "$snapshot_temp_path"
  \command \mkdir -p "$snapshot_temp_path"

  rvm_log "Extracting snapshot"
  (
    __rvm_cd "$snapshot_temp_path"
    __rvm_tar xzf "$snapshot_archive"
    result="$?"
    __error_on_result "$result" "Error extracting the archive '$snapshot_archive'" && return "$result"
  )

  rvm_log "Restoring user settings"
  __rvm_cp -f "$snapshot_temp_path/db" "$rvm_user_path/db"

  rvm_log "Installing rvm-managed packages"
  for snapshot_package in $(\command \cat "$snapshot_temp_path/pkg")
  do
    "$rvm_scripts_path/package" install "$snapshot_package"
    result="$?"
    __error_on_result "$result" "Error installing package '$snapshot_package'" && return "$result"
  done
  unset snapshot_package

  rvm_log "Installing rubies"

  chmod +x "$snapshot_temp_path/install-rubies.sh"
  __rvm_sed_i "${snapshot_temp_path}/install-rubies.sh" -e '1 s/#!\/usr\/bin\/env bash -e/#!\/usr\/bin\/env bash\n\nset -e/'

  "$snapshot_temp_path/install-rubies.sh"
  result="$?"

  __error_on_result "$result" "Error importing rubies." && return "$result"

  rvm_create_flag=1

  rvm_log "Setting up gemsets"

  (
    __rvm_cd "$snapshot_temp_path/gems"

    gems=($(__rvm_find . -mindepth 0 -maxdepth 0 -type f "${name_opt}" '*.gems' | __rvm_sed 's/.gems$//'))

    for snapshot_gemset in "${gems[@]//.\/}"
    do

      __rvm_become "$snapshot_gemset"
      result="$?"

      __error_on_result "$result" \
        "Error becoming '$snapshot_gemset'" && return "$result"

      mkdir -p "$GEM_HOME/cache/"

      __rvm_cp -Rf "$snapshot_gemset/" "$GEM_HOME/cache/"
      result="$?"

      __error_on_result "$result" \
        "Error copying across cache for $snapshot_gemset" && return "$result"

      "$rvm_scripts_path/gemsets" import "$snapshot_gemset" >/dev/null 2>&1
      result="$?"

      __error_on_result "$result" \
        "Error importing gemset for $snapshot_gemset" && return "$result"
    done
  )

  rvm_log "Restoring aliases"

  while read -r package_info
  do
    # Note: this assumes an '=' int the input...
    alias_name="${package_info/=*}"
    alias_ruby="${package_info/*=}"

    "$rvm_scripts_path/alias" create "$alias_name" "$alias_ruby"
  done < "$snapshot_temp_path/alias"

  rvm_log "Cleaning up load process"
  __rvm_rm_rf "$snapshot_temp_path"

  rvm_log "Loaded snapshot from $(basename "$snapshot_archive")"
}

snapshot_usage()
{
  echo "Usage: rvm snapshot {save,load} file" >&2
  return 1
}


args=($*)
action="${args[0]}"
args="$(echo ${args[@]:1})" # Strip trailing / leading / extra spacing.

case "$action" in
  save) snapshot_save "$args" ;;
  load) snapshot_load "$args" ;;
  *)    snapshot_usage ;;
esac

exit $?
